package cmp.compile.panels;

/**************************************************************
 * This defines the Blast panel for the Main window
 * It also has the action for RunBlast and executes it.
 * EditBlastPanel defines the Setting panel. 
 */
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;

import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.event.CaretEvent;
import javax.swing.event.CaretListener;

import cmp.compile.DoBlast;
import cmp.main.Globals;

import util.Debug.ErrorReport;

public class BlastPanel extends JPanel {
	private static final long serialVersionUID = 312139563542324851L;

	public BlastPanel(CompilePanel parentPanel) {
		theParentPanel = parentPanel;
		setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
		setAlignmentX(Component.LEFT_ALIGNMENT);
		setBackground(Globals.BGCOLOR);
		
		editPanel = new EditBlastPanel(this);
		editPanel.fillEmptyFieldsWithDefaults();
		
		lblBlastSummaryFile = new JLabel(" ");
		lblBlastSummaryParams = new JLabel(" ");
		lblBlastSummaryFilter = new JLabel(" ");
		
		/** Main Panel **/
		btnRunBlast = new JButton("Run Blast");
		//btnRunBlast.setBackground(Globals.FUNCTIONCOLOR);
		btnRunBlast.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				boolean filtExists = new File(editPanel.getFilteredBlastFileName()).exists();
				boolean origExists = new File(editPanel.getBlastFileName()).exists();
				boolean runBlast = !editPanel.useBlast();
				boolean runFiltering = filterBlast();

				if (runBlast && origExists)
				{
					if(JOptionPane.showConfirmDialog(theParentPanel, "Overwrite Blast file?", "Blast", 
							JOptionPane.YES_NO_OPTION, JOptionPane.PLAIN_MESSAGE) != JOptionPane.YES_OPTION)
					{
						runBlast = false;	
					}
				}
				if (runFiltering && filtExists && !runBlast) // no point asking this if we're redoing the blast...
				{
					if(JOptionPane.showConfirmDialog(theParentPanel, "Redo filtering?", "Filtering", 
							JOptionPane.YES_NO_OPTION, JOptionPane.PLAIN_MESSAGE) != JOptionPane.YES_OPTION)
					{
						runFiltering = false;
					}
				}
				if(runBlast) {
					if (DoBlast.runBlast(theParentPanel, editPanel.getBlastFileName())) { 
						editPanel.setUseBlast(true);
						setBlastSummary();

						if (runFiltering)
							DoBlast.cleanBlast(new File(editPanel.getBlastFileName()),theParentPanel);
					}
				}
			}
		});
		lblCPUs = new JLabel("#CPUs");
		txtCPUs = new JTextField(3);
		txtCPUs.setText(Globals.CompilePanel.BLASTFILTEX);
		txtCPUs.setMaximumSize(txtCPUs.getPreferredSize());
		txtCPUs.setMinimumSize(txtCPUs.getPreferredSize());
		
		btnBlastSettings = new JButton("Settings");
		btnBlastSettings.setBackground(Globals.MENUCOLOR);
		btnBlastSettings.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				strTempBlastFile = editPanel.getBlastFileName();
				strTempBlastParams = editPanel.getParams();
				bTempMode = editPanel.useBlast();
				bTempFilter = editPanel.filterBlast();
				strTempID = editPanel.getFiltID();
				strTempExtra = editPanel.getFiltExtra();
				
				//If either field is blank, fill with default value
				editPanel.fillEmptyFieldsWithDefaults();
				editPanel.updatePanel();
				theParentPanel.setMainPanelVisible(false);
				setVisible(true);
				headerPanel.setVisible(false);
				editPanel.setVisible(true);
				buttonPanel.setVisible(false);
			}
		});
							
/** Back to main panel **/
		lblBlast = new JLabel("2. Blast");
		
		headerPanel = CompilePanel.getPanel(false);
		buttonPanel = CompilePanel.getPanel(false);
		
		headerPanel.add(lblBlast);
		headerPanel.add(Box.createVerticalStrut(10));
		
		buttonPanel.add(lblBlastSummaryFile);
		buttonPanel.add(Box.createVerticalStrut(5));
		buttonPanel.add(lblBlastSummaryParams);
		buttonPanel.add(Box.createVerticalStrut(5));
		buttonPanel.add(lblBlastSummaryFilter);
		buttonPanel.add(Box.createVerticalStrut(5));

		JPanel row = CompilePanel.getPanel(true);
		row.add(lblCPUs);
		row.add(Box.createHorizontalStrut(5));
		row.add(txtCPUs);
		row.add(Box.createHorizontalStrut(10));
		
		row.add(btnBlastSettings);
		row.add(Box.createHorizontalStrut(10));
		row.add(btnRunBlast);
		
		buttonPanel.add(row);
		
		add(Box.createVerticalStrut(10));
		add(headerPanel);
		add(buttonPanel);

		add(Box.createVerticalStrut(10));
		
		add(editPanel);

		editPanel.setVisible(false);
		
		setBlastSummary();
	}
	
	public void setUseBlastPanel(boolean useBlast) { 
		editPanel.setUseBlast(useBlast);
		setBlastSummary();
	}
	
	public CompilePanel getParentPanel() { return theParentPanel; }
	
	public void resetValsOnDiscard() {
		editPanel.setBlastFileName(strTempBlastFile);
		editPanel.setParams(strTempBlastParams);
		editPanel.setUseBlast(bTempMode);
		editPanel.setUseFilter(bTempFilter);
		editPanel.setFiltID(strTempID);
		editPanel.setFiltExtra(strTempExtra);
	}
	
	public void setBlastSummary() {
		if(theParentPanel.getProjectPanel().getSelectedProjectName() == null) {
			lblBlastSummaryFile.setText("No project selected");
			lblBlastSummaryParams.setText("");
			lblBlastSummaryFilter.setText("");
		}
		else {
			String blastFile = editPanel.getBlastFileName();
			String displayFile = blastFile;
			if(blastFile.startsWith(theParentPanel.getCurrentProjectDirectory()))
				displayFile = blastFile.substring(theParentPanel.getCurrentProjectDirectory().length() + 1);

			if((new File(blastFile)).exists() && editPanel.useBlast()) {
				lblBlastSummaryFile.setText("Use Blast file: " + displayFile);
				lblBlastSummaryParams.setText("");
				btnRunBlast.setEnabled(false);
			}
			else {
				lblBlastSummaryFile.setText("Generate blast file using parameters " + editPanel.getParams());
				btnRunBlast.setEnabled(true);
			}
			if(editPanel.filterBlast()) {
				lblBlastSummaryFilter.setText("Filter with " + editPanel.getFiltID() + "% identity and " + editPanel.getFiltExtra() + " max non-align");
			}
			else
				lblBlastSummaryFilter.setText("");
		}		
	}
	public void setProjectSelected(boolean enabled) {
		btnBlastSettings.setEnabled(enabled);
		lblBlastSummaryFile.setEnabled(enabled);
		lblBlastSummaryParams.setEnabled(enabled);
		lblBlastSummaryFilter.setEnabled(enabled);
		lblCPUs.setEnabled(enabled);
		txtCPUs.setEnabled(enabled);
		btnRunBlast.setEnabled(enabled);
	}
		
	public String getBlastFileForCfgFile() { 
		String path = editPanel.getBlastFileName(); 
		if (path.equals(getDefaultBlastDirFullPath()))
		{
			path = getDefaultBlastDirRelPath();
		}
		File fp = new File(path);
		if (!fp.exists())
		{
			return "";
		}
		return path;
	}
	public String getFilteredBlastFileName() {return editPanel.getFilteredBlastFileName();}

	public String getBlastFile() {
		try {
			// Determine whether the ultimate blast file to be loaded is the filtered or unfiltered. 
			String blastFileFilt = editPanel.getFilteredBlastFileName();
			String blastFileUnfilt =  editPanel.getBlastFileName();
			boolean blastFileExists = (new File(blastFileUnfilt)).exists();
			boolean filtFileExists = (new File(blastFileFilt)).exists();
			
			String blastFile = (filterBlast() ? blastFileFilt : blastFileUnfilt);
			boolean neededFileExists = (filterBlast() ? filtFileExists : blastFileExists);
			
			if(neededFileExists && editPanel.useBlast())
				return blastFile;
			
				String msg = "";
				
				if (filterBlast())
				{
					if (blastFileExists && editPanel.useBlast())
					{
						// The unfiltered blast file is there, but the filtered is not (else would have returned above)
						// Generate the filtered without any message. 
						DoBlast.cleanBlast(new File(blastFileUnfilt), theParentPanel);
						return blastFileFilt;
					}
	
				}
				// If we get here then either filtering is off, or the original blast file does not exist. 
				// In either case we need to prompt about the original blast file. 

				if(editPanel.useBlast()) // WN - this now should never happen since the keep method checks existence 
					msg = "Blast file " + blastFile + " does not exist, generate?";
				else if((new File(blastFile)).exists()) 
					msg = "Overwrite blast file?"; // Should not be able to reach here?
				else
					msg = "Generate blast file?";
				
				if(JOptionPane.showConfirmDialog(theParentPanel, msg, "Blast file needed", 
						JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE, null) == JOptionPane.OK_OPTION)
				{
					if (DoBlast.runBlast(theParentPanel, blastFileUnfilt)) {
						editPanel.setUseBlast(true);
						setBlastSummary();
						return blastFile;
					}
				}				
		}
		catch(Exception e) {
			ErrorReport.prtReport(e, "Error getting blast file");
		}
		return null;
	}
	
	public void setMainPanelVisible(boolean visible) {
		headerPanel.setVisible(visible);
		buttonPanel.setVisible(visible);
		theParentPanel.setMainPanelVisible(visible);
	}
	// This is called just after the blast file is created, and also when loading
	// the cfg file. In the latter case, if the file doesn't exist, don't set useBlast
	public void setBlastFile(String bFile) { 
		editPanel.setBlastFileName(bFile); 
		editPanel.setUseBlast((new File(bFile)).exists());
	}
	public String getBlastParams() { return editPanel.getParams(); }
	public String getFilterID() { return editPanel.getFiltID(); }
	public String getFilterExtra() { return editPanel.getFiltExtra(); }
	public Boolean filterBlast() { return editPanel.filterBlast(); }
	public String getFilterBlastName() { return editPanel.getFilteredBlastFileName(); }
	
	public int getCPUs() {
		try {
			String n = txtCPUs.getText();
			nCPUs = Integer.parseInt(n);
			return nCPUs;
		}
		catch (Exception e) {
			JOptionPane.showMessageDialog(this,  
					"#CPUs must be an integer", "Error", JOptionPane.PLAIN_MESSAGE);
			return 0;
		}
	}
	public void setBlastParams(String params) { 
		editPanel.setParams(params); 
		setBlastSummary();
	}
	public void setFilterID(String id) { 
		editPanel.setFiltID(id);
		setBlastSummary();
	}
	public void setFilterExtra(String extra) { 
		editPanel.setFiltExtra(extra); 
		setBlastSummary();
	}
	public void setFilterBlast(boolean setBlast) { 
		editPanel.setUseFilter(setBlast); 
		setBlastSummary();
	}
	public void setFilterBlastName(String name) { 
		editPanel.setFilteredBlastFileName(name); 
		setBlastSummary();
	}
	public String getDefaultBlastTextEntry() { return getDefaultBlastDirRelPath() + "/"  + Globals.CompilePanel.BLASTTAB; }
	
	// WN: build the full path to default blast location so we can tell if the user-selected
	// path starts with this or not.
	public String getDefaultBlastDirFullPath()
	{
		String sdir = getDefaultBlastDirRelPath();
		File dir = new File(sdir);
		return dir.getAbsolutePath();
	}
	public String getDefaultBlastDirRelPath()
	{
		String projDir = theParentPanel.getCurProjectDirectory();
		if (!projDir.endsWith("/")) projDir += "/"; 
		return projDir + Globals.CompilePanel.BLASTDIR;
	}	
	private JButton btnBlastSettings = null;
	private JLabel lblBlastSummaryFile = null;
	private JLabel lblBlastSummaryParams = null;
	private JLabel lblBlastSummaryFilter = null;
	private JButton btnRunBlast = null;
	private JLabel lblBlast = null;
	private JLabel lblCPUs = null;
	private JTextField txtCPUs = null;

	public EditBlastPanel editPanel = null;
	private JPanel headerPanel = null;
	private JPanel buttonPanel = null;
	private CompilePanel theParentPanel = null;
	
	private String strTempBlastFile = ""; 
	private String strTempBlastParams = "";
	private boolean bTempMode = false;
	private boolean bTempFilter = false;
	private String strTempID = "";
	private String strTempExtra = "";
	private int nCPUs=1;
}
